/* http://www.apache.org/licenses/LICENSE-2.0 */
/* Many thanks to the writor of libaco Sen Han <00hnes@gmail.com> */

#include <stdio.h>
#include "mco.h"

void foo(int ct) {
	printf("co: %p: yield to main_co: %d\n", mco_get_co(), *((int*)(mco_get_arg())));
	mco_yield();
	*((int*)(mco_get_arg())) = ct + 1;
}

void co_fp0() {
	printf("co: %p: entry: %d\n", mco_get_co(), *((int*)(mco_get_arg())));
	int ct = 0;
	while(ct < 6){
		foo(ct);
		ct++;
	}
	printf("co: %p:  exit to main_co: %d\n", mco_get_co(), *((int*)(mco_get_arg())));
	return;
}

int main() {

	mco_thread_init();

	int co0_ct_arg_point_to_me = 0;
	void * co0 = mco_create(co_fp0, &co0_ct_arg_point_to_me, 0);

	int co1_ct_arg_point_to_me = 0;
	void * co1 = mco_create(co_fp0, &co1_ct_arg_point_to_me, 0);

	int ct = 0;
	while(ct < 6){

		if (mco_is_end(co0))	{
			printf("assert(co0->is_end == 0);\n");
		}
		printf("main_co: yield to co0: %p: %d\n", co0, ct);
		mco_resume(co0);

		if (mco_is_end(co1))	{
			printf("assert(co1->is_end == 0);\n");
		}
		printf("main_co: yield to co1: %p: %d\n", co0, ct);
		mco_resume(co1);

		if (co0_ct_arg_point_to_me != ct)	{
			printf("assert(co0_ct_arg_point_to_me == ct);\n");
		}

		if (co1_ct_arg_point_to_me != ct)	{
			printf("assert(co1_ct_arg_point_to_me == ct);\n");
		}

		ct++;
	}

	printf("main_co: yield to co0, co1: %p: %d\n", co0, ct);
	mco_resume(co0);
	mco_resume(co1);

	if (co0_ct_arg_point_to_me != ct)	{
		printf("assert(co0_ct_arg_point_to_me == ct);\n");
	}

	if (!mco_is_end(co0))	{
		printf("assert(co0->is_end);\n");
	}

	if (co1_ct_arg_point_to_me != ct)	{
		printf("assert(co1_ct_arg_point_to_me == ct);\n");
	}

	if (!mco_is_end(co1))	{
		printf("assert(co1->is_end);\n");
	}

	if (mco_check_stack(co0))	{
		printf("fatal error: co0 stack overflow\n");
	}

	if (mco_check_stack(co1))	{
		printf("fatal error: co1 stack overflow\n");
	}

	printf("main_co: destroy and exit\n");

	mco_destroy(co0);
	co0 = NULL;

	mco_destroy(co1);
	co1 = NULL;

	return 0;
}

/* eof */
